<template>
    <div id="test" class="test-view">
        <Map ref="mapRef" @map-loaded="onMapLoaded" @full-screen="handleFullScreen('test')" />
        <div class="form-container">
            <video ref="videoRef" muted controls width="300" height="220" src="/video/test.mp4" autoplay loop crossorigin="anonymous"></video>
            <el-form :model="form" label-width="60px" label-position="left" size="small">
                <el-form-item label="翻转">
                    <el-slider v-model="form.rotationX" :show-tooltip="true" @input="updateVideoProjection" :min="-180" :max="180" />
                </el-form-item>
                <el-form-item label="旋转">
                    <el-slider v-model="form.rotationY" :show-tooltip="true" @input="updateVideoProjection" :min="-360" :max="360" />
                </el-form-item>
                <el-form-item label="夹角">
                    <el-slider v-model="form.fov" :show-tooltip="true" @input="updateVideoProjection" :min="1" :max="90" />
                </el-form-item>
                <el-form-item label="透明">
                    <el-slider v-model="form.alpha" :show-tooltip="true" @input="updateVideoProjection" :step="0.1" :min="0" :max="1" />
                </el-form-item>
                <el-form-item label="投影线">
                    <el-switch v-model="form.debugFrustum" @change="toggleFrustum" />
                </el-form-item>
            </el-form>
        </div>
    </div>
</template>

<script setup>
import { ref, reactive, onBeforeUnmount } from 'vue'
import Map from '@/components/Map.vue'
import * as Cesium from 'cesium'

const mapRef = ref(null)
const videoRef = ref(null)

let cesiumTools = null
let viewer = null
let videoEntity = null
let frustumPrimitive = null

const form = reactive({
    rotationX: 53,
    rotationY: 3,
    fov: 12,
    alpha: 1,
    debugFrustum: true
})

// 地图加载完成的回调
const onMapLoaded = (tools, cesiumViewer) => {
    console.log('Map loaded')
    cesiumTools = tools
    viewer = cesiumViewer
    initVideoProjection()
}

// 初始化视频投影
const initVideoProjection = () => {
    if (!viewer || !videoRef.value) return

    // 定义视频投影的基本参数
    const centerLon = 118.6383
    const centerLat = 24.9114
    const height = 0
    const cameraHeight = height + 1000  // 视锥体顶点高度

    // 创建视频材质
    const videoElement = videoRef.value
    const videoMaterial = new Cesium.ImageMaterialProperty({
        image: videoElement,
        transparent: true,
        color: new Cesium.CallbackProperty(() => {
            return new Cesium.Color(1.0, 1.0, 1.0, form.alpha)
        }, false)
    })

    // 计算视频投影范围
    const updateRectangle = () => {
        // 创建一个临时相机来计算视锥体投影
        const camera = new Cesium.Camera(viewer.scene);
        
        // 设置相机位置
        camera.position = Cesium.Cartesian3.fromDegrees(
            centerLon,
            centerLat,
            cameraHeight
        );
        
        // 设置视锥体参数
        camera.frustum = new Cesium.PerspectiveFrustum({
            fov: Cesium.Math.toRadians(form.fov),
            aspectRatio: 16.0 / 9.0,
            near: 1.0,
            far: 2000.0
        });
        
        // 计算旋转矩阵
        const pitchQuat = Cesium.Quaternion.fromAxisAngle(
            Cesium.Cartesian3.UNIT_X,
            Cesium.Math.toRadians(form.rotationX)
        );
        const headingQuat = Cesium.Quaternion.fromAxisAngle(
            Cesium.Cartesian3.UNIT_Z,
            Cesium.Math.toRadians(form.rotationY)
        );
        
        // 组合旋转
        const rotation = Cesium.Quaternion.multiply(
            headingQuat,
            pitchQuat,
            new Cesium.Quaternion()
        );
        
        // 计算视锥体的四个角点在地面的投影
        const corners = [];
        const distance = cameraHeight - height;
        const tanHalfFov = Math.tan(Cesium.Math.toRadians(form.fov / 2));
        const tanHalfFovWidth = tanHalfFov * (16/9);
        
        // 计算未旋转时的视锥体四个角点（相对于相机位置）
        const cornerVectors = [
            new Cesium.Cartesian3(-tanHalfFovWidth * distance, -tanHalfFov * distance, -distance),
            new Cesium.Cartesian3(tanHalfFovWidth * distance, -tanHalfFov * distance, -distance),
            new Cesium.Cartesian3(tanHalfFovWidth * distance, tanHalfFov * distance, -distance),
            new Cesium.Cartesian3(-tanHalfFovWidth * distance, tanHalfFov * distance, -distance)
        ];
        
        // 应用旋转到每个角点
        cornerVectors.forEach(corner => {
            // 旋转角点
            const rotatedCorner = Cesium.Matrix3.fromQuaternion(rotation, new Cesium.Matrix3());
            const transformedCorner = Cesium.Matrix3.multiplyByVector(
                rotatedCorner,
                corner,
                new Cesium.Cartesian3()
            );
            
            // 计算地面投影点的经纬度
            const projectedPoint = Cesium.Cartesian3.add(
                camera.position,
                transformedCorner,
                new Cesium.Cartesian3()
            );
            const cartographic = Cesium.Cartographic.fromCartesian(projectedPoint);
            corners.push({
                longitude: Cesium.Math.toDegrees(cartographic.longitude),
                latitude: Cesium.Math.toDegrees(cartographic.latitude)
            });
        });
        
        // 计算包围这些点的矩形
        const west = Math.min(...corners.map(c => c.longitude));
        const east = Math.max(...corners.map(c => c.longitude));
        const south = Math.min(...corners.map(c => c.latitude));
        const north = Math.max(...corners.map(c => c.latitude));
        
        return Cesium.Rectangle.fromDegrees(west, south, east, north);
    }

    // 创建视频实体
    videoEntity = viewer.entities.add({
        rectangle: {
            coordinates: new Cesium.CallbackProperty(() => {
                return updateRectangle() // 返回一个新的矩形坐标数组
            }, false),
            material: videoMaterial,
            rotation: new Cesium.CallbackProperty(() => {
                return Cesium.Math.toRadians(form.rotationY)
            }, false),
            stRotation: new Cesium.CallbackProperty(() => {
                return Cesium.Math.toRadians(form.rotationX)
            }, false)  
        }
    })

    // 设置相机视角 - 调整视角以便更好地观察视频投影
    viewer.camera.flyTo({
        destination: Cesium.Cartesian3.fromDegrees(centerLon, centerLat - 0.005, height + 500),
        orientation: {
            heading: Cesium.Math.toRadians(0),
            pitch: Cesium.Math.toRadians(-30),
            roll: 0
        },
        complete: () => {
            // 相机飞行完成后，确保视锥体显示正确
            if (form.debugFrustum) {
                createFrustumPrimitive()
            }
            // 强制刷新视图
            viewer.scene.requestRender()
        }
    })
}

// 更新视频投影
const updateVideoProjection = () => {
    // 视频投影会通过CallbackProperty自动更新
    // 但我们需要手动更新视锥体
    if (form.debugFrustum) {
        createFrustumPrimitive()
    }
    
    // 强制刷新视图以确保更新生效
    viewer.scene.requestRender()
}

// 创建视锥体线框
const createFrustumPrimitive = () => {
    if (!viewer) return
    
    // 使用与视频投影相同的位置参数
    const centerLon = 118.6383
    const centerLat = 24.9114
    const height = 0
    const cameraHeight = height + 1000  // 视锥体顶点高度
    
    // 移除旧的视锥体
    if (frustumPrimitive) {
        viewer.scene.primitives.remove(frustumPrimitive)
    }
    
    try {
        // 创建自定义视锥体
        const camera = new Cesium.Camera(viewer.scene)
        
        // 设置相机位置
        camera.position = Cesium.Cartesian3.fromDegrees(
            centerLon,
            centerLat, 
            cameraHeight
        )
        
        // 设置视锥体参数
        camera.frustum = new Cesium.PerspectiveFrustum({
            fov: Cesium.Math.toRadians(form.fov),
            aspectRatio: 16.0 / 9.0,
            near: 1.0,
            far: 2000.0
        })
        
        // 计算旋转矩阵
        const pitchQuat = Cesium.Quaternion.fromAxisAngle(
            Cesium.Cartesian3.UNIT_X,
            Cesium.Math.toRadians(form.rotationX)
        );
        const headingQuat = Cesium.Quaternion.fromAxisAngle(
            Cesium.Cartesian3.UNIT_Z,
            Cesium.Math.toRadians(form.rotationY)
        );
        
        // 组合旋转
        const rotation = Cesium.Quaternion.multiply(
            headingQuat,
            pitchQuat,
            new Cesium.Quaternion()
        );
        
        // 计算默认方向（向下）
        const defaultDirection = new Cesium.Cartesian3(0, 0, -1);
        const defaultUp = new Cesium.Cartesian3(0, 1, 0);
        const defaultRight = new Cesium.Cartesian3(1, 0, 0);
        
        // 应用旋转到方向向量
        const rotationMatrix = Cesium.Matrix3.fromQuaternion(rotation, new Cesium.Matrix3());
        
        const direction = Cesium.Matrix3.multiplyByVector(
            rotationMatrix,
            defaultDirection,
            new Cesium.Cartesian3()
        );
        const up = Cesium.Matrix3.multiplyByVector(
            rotationMatrix,
            defaultUp,
            new Cesium.Cartesian3()
        );
        const right = Cesium.Matrix3.multiplyByVector(
            rotationMatrix,
            defaultRight,
            new Cesium.Cartesian3()
        );
        
        // 设置相机方向
        camera.direction = direction;
        camera.up = up;
        camera.right = right;
        
        // 添加新的视锥体
        frustumPrimitive = viewer.scene.primitives.add(new Cesium.DebugCameraPrimitive({
            camera: camera,
            color: Cesium.Color.YELLOW,
            updateOnChange: false,
            show: true
        }))
        
        console.log('视锥体已创建', {
            rotationX: form.rotationX,
            rotationY: form.rotationY,
            fov: form.fov
        })
    } catch (error) {
        console.error('创建视锥体失败', error)
    }
    
    // 强制刷新视图
    viewer.scene.requestRender()
}

// 切换视锥体显示
const toggleFrustum = () => {
    if (form.debugFrustum) {
        // 如果开启视锥体显示，创建新的视锥体
        createFrustumPrimitive()
    } else if (frustumPrimitive) {
        // 如果关闭视锥体显示，移除现有视锥体
        viewer.scene.primitives.remove(frustumPrimitive)
        frustumPrimitive = null
    }
    
    // 强制刷新视图以确保更新生效
    viewer.scene.requestRender()
}

// 添加全屏处理方法
const handleFullScreen = (id) => {
    cesiumTools.divFullScreen(id)
}

// 组件销毁时清理资源
onBeforeUnmount(() => {
    if (viewer) {
        if (videoEntity) {
            viewer.entities.remove(videoEntity)
        }
        if (frustumPrimitive) {
            viewer.scene.primitives.remove(frustumPrimitive)
        }
    }
})
</script>

<style scoped lang="scss">
.test-view {
    width: 100%;
    height: 100vh;
    position: relative;
}

.form-container {
    position: absolute;
    left: 10px;
    top: 10px;
    padding: 10px 15px;
    border-radius: 4px;
    border: 1px solid rgba(128, 128, 128, 0.5);
    color: #ffffff;
    background: rgba(0, 0, 0, 0.4);
    box-shadow: 0 3px 14px rgb(128 128 128 / 50%);
    max-width: 300px;

    :deep(.el-form-item__label) {
        color: white;
    }
}
</style>